package com.zkhz.base.common.dto;

import com.alibaba.fastjson.JSON;
import com.zkhz.base.constant.enums.ErrorStatus;
import com.zkhz.base.util.system.I18nUtil;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.experimental.Accessors;
import org.springframework.http.HttpStatus;
import org.springframework.util.StringUtils;

import java.util.HashMap;
import java.util.Map;

/**
 * @Description 统一响应传输对象
 *
 * @author wuzeqin
 * @date 2020/5/18
 *
 * @param <T> 数据类型
 */
@Data
@Accessors(chain = true)
public class ResponseDTO<T> {

    public static final String SUCCESS = "1";

    public static final String FAIL = "0";

    @ApiModelProperty(value = "返回结果(0失败，1成功)", allowableValues = "0,1")
    private String code = SUCCESS;

    @ApiModelProperty(value = "状态码（标准）")
    private String status;

    @ApiModelProperty(value = "状态描述（标准）")
    private String detail;

    @ApiModelProperty(value = "自定义说明")
    private String msg;

    @ApiModelProperty(value = "响应数据")
    private T data;

    public static boolean isSuccess(ResponseDTO<?> responseDTO) {
        return responseDTO != null && SUCCESS.equals(responseDTO.getCode());
    }

    public static <S> ResponseDTO<S> ok(S data) {
        ResponseDTO<S> responseDTO = parse(HttpStatus.OK);
        responseDTO.setData(data);
        return responseDTO;
    }

    public static <S> ResponseDTO<S> fail(String msg) {
        return status(ErrorStatus.B0001).message(msg).build();
    }

    public static <S> ResponseDTO<S> created(S data) {
        ResponseDTO<S> responseDTO = parse(HttpStatus.CREATED);
        responseDTO.setData(data);
        return responseDTO;
    }

    public static <S> ResponseDTO<S> noContent() {
        return parse(HttpStatus.NO_CONTENT);
    }

    public static Builder status(ErrorStatus errorStatus) {
        return new DefaultBuilder(errorStatus);
    }

    public static Builder status(String statusCode) {
        return new DefaultBuilder(statusCode);
    }

    public static Builder status(HttpStatus httpStatus) {
        return new DefaultBuilder(httpStatus);
    }

    public static Builder status(int status) {
        return new DefaultBuilder(status);
    }

    public interface Builder {

        <S> ResponseDTO<S> build();

        <S> ResponseDTO<S> data(S data);

        Builder message(String message);
    }


    private static class DefaultBuilder implements Builder {

        private final Object status;

        private String msg;

        DefaultBuilder(Object status) {
            this.status = status;
        }

        @Override
        public <S> ResponseDTO<S> build() {
            ResponseDTO<S> responseDTO = null;
            if (status instanceof String) {
                responseDTO = parse((String) status);
            }
            if (status instanceof Integer) {
                responseDTO = parse((Integer) status);
            }
            if (status instanceof ErrorStatus) {
                responseDTO = parse((ErrorStatus) status);
            }
            if (status instanceof HttpStatus) {
                responseDTO = parse((HttpStatus) status);
            }
            if (responseDTO == null) {
                responseDTO = parse(ErrorStatus.UNKNOWN);
            }

            if(responseDTO.getStatus().charAt(0) != '2') {
                responseDTO.setCode(FAIL);
            }
            if (StringUtils.isEmpty(msg)) {
                msg = responseDTO.getDetail();
            }
            responseDTO.setMsg(msg);
            return responseDTO;
        }

        @Override
        public <S> ResponseDTO<S> data(S data) {
            ResponseDTO<S> responseDTO = build();
            responseDTO.setData(data);
            return responseDTO;
        }

        @Override
        public Builder message(String message) {
            this.msg = message;
            return this;
        }
    }

    private static <S> ResponseDTO<S> parse(String status) {
        return parse(ErrorStatus.resolve(status));
    }

    private static <S> ResponseDTO<S> parse(ErrorStatus errorStatus) {
        ResponseDTO<S> responseDTO = new ResponseDTO<>();
        responseDTO.setStatus(errorStatus.getStatus());
        responseDTO.setDetail(errorStatus.getDetail());
        return responseDTO;
    }

    private static <S> ResponseDTO<S> parse(HttpStatus status) {
        ResponseDTO<S> responseDTO = new ResponseDTO<>();
        responseDTO.setStatus(String.valueOf(status.value()));
        responseDTO.setDetail(I18nUtil.getMessage(status.getReasonPhrase()));
        return responseDTO;
    }

    private static <S> ResponseDTO<S> parse(int status) {
        HttpStatus httpStatus = HttpStatus.resolve(status);
        return httpStatus != null ? parse(httpStatus) : parse(ErrorStatus.UNKNOWN);
    }


    public static void main(String[] args) {
        //最佳实践1
        Map<String, Object> map = new HashMap<>();
        map.put("name", "张三");
        map.put("sex", "男");
        ResponseDTO<Map<String, Object>> ok = ResponseDTO.ok(map);
        System.out.println(JSON.toJSONString(ok));

        //最佳实践2
        ResponseDTO<String> error = ResponseDTO.status(500).message("我的天，空指针异常！").build();
        System.out.println(JSON.toJSONString(error));

        //最佳实践3
        ResponseDTO<Void> noContent = ResponseDTO.noContent();
        System.out.println(JSON.toJSONString(noContent));

        //最佳实践4
        ResponseDTO<String> error4 = ResponseDTO.status(ErrorStatus.A0001).data("{错误数据对象}");
        System.out.println(JSON.toJSONString(error4));
    }

}
